package app

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	consts "qrsj-collect/backend/const"
	"qrsj-collect/backend/utils"
	"regexp"
	"strings"

	"github.com/imroc/req/v3"
	jsoniter "github.com/json-iterator/go"
	"github.com/wailsapp/wails/v2/pkg/runtime"
)

type UpdateApp struct {
	ctx         context.Context
	json        jsoniter.API
	client      *req.Client
	isParsed    bool   // 是否解析过(热更新时重复flag.Parse会报错)
	isUpdate    int    // 是否为更新程序
	downloadUrl string // 下载地址
	pwd         string // 密码
	fileIndex   int    // 文件索引
}

type UpdateAppInfo struct {
	AppFolderName string `json:"app_folder_name"`
	NewVersion    string `json:"new_version"`
}

func NewUpdateApp() *UpdateApp {
	return &UpdateApp{}
}

func (a *UpdateApp) Startup(ctx context.Context) {
	a.ctx = ctx
	a.json = jsoniter.ConfigCompatibleWithStandardLibrary
	a.client = req.C().SetUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36")
}

// 获取应用版本
func (a *UpdateApp) GetAppVersion(downloadUrl, pwd string, fileIndex int) map[string]interface{} {
	a.downloadUrl = downloadUrl
	a.pwd = pwd
	a.fileIndex = fileIndex
	var updateAppInfo UpdateAppInfo
	resp, err := a.client.R().Get(downloadUrl)
	if err != nil {
		errMsg := fmt.Sprintf("获取版本号失败: %s", err.Error())
		log.Println(errMsg)
		return map[string]interface{}{
			"code": http.StatusBadRequest,
			"msg":  errMsg,
			"data": updateAppInfo,
		}
	}
	respStr, _ := resp.ToString()
	appNamePattern := regexp.MustCompile(`<title>(.+)</title>`)
	if appNameMatch := appNamePattern.FindStringSubmatch(respStr); appNameMatch != nil {
		// 先判断是否有_分隔符
		if !strings.Contains(appNameMatch[1], "_") {
			updateAppInfo.AppFolderName = appNameMatch[1]
			updateAppInfo.NewVersion = "0"
		} else {
			// appNameMatch[1]取到的内容是appName_version
			updateAppInfo.AppFolderName = strings.Split(appNameMatch[1], "_")[0]
			updateAppInfo.NewVersion = strings.Split(appNameMatch[1], "_")[1]
		}
	}
	fmt.Println("文件夹名称:", updateAppInfo.AppFolderName)
	fmt.Println("版本号:", updateAppInfo.NewVersion)
	return map[string]interface{}{
		"code": http.StatusOK,
		"msg":  "获取版本号成功",
		"data": updateAppInfo,
	}
}

// 启动更新程序
func (a *UpdateApp) StartUpdate() map[string]interface{} {
	appName := filepath.Base(os.Args[0])
	dir, _ := os.Getwd()
	updatePath := filepath.Join(dir, "update.exe")
	fmt.Println("updatePath", updatePath)
	exists := utils.FileExists(updatePath)
	if !exists {
		log.Println("更新程序不存在")
		return map[string]interface{}{
			"code": http.StatusBadRequest,
			"msg":  "更新程序不存在,请检查路径",
		}
	}
	fmt.Println("更新程序路径", exists, updatePath)
	args := []string{
		"--startKey", consts.StartKey,
		"--updateUrl", a.downloadUrl,
		"--updatePwd", a.pwd,
		"--updateIndex", fmt.Sprintf("%d", a.fileIndex),
		"--sourceAppName", appName,
	}
	fmt.Println("更新程序参数", args)
	cmd := exec.Command(updatePath, args...)
	err := cmd.Start()
	if err != nil {
		log.Println("更新程序启动失败", err)
		return map[string]interface{}{
			"code": http.StatusBadRequest,
			"msg":  "更新程序启动失败,请检查路径",
		}
	}
	runtime.Quit(a.ctx)
	return map[string]interface{}{
		"code": http.StatusOK,
		"msg":  "更新程序启动成功",
	}
}

// 判断启动程序是否有更新标识
func (a *UpdateApp) CheckStartIsUpdate() bool {
	if !a.isParsed {
		flag.IntVar(&a.isUpdate, "isUpdate", 0, "是否为更新程序")
		flag.Parse()
		a.isParsed = true
	}
	return a.isUpdate == 1
}
